﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Collections.ObjectModel;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Resources;
using System.Windows.Markup;
using SmartPaginator.Extensions;

namespace SmartPaginator.Elements
{
    public class PageElement : Control
    {
        #region Constructor

        public PageElement(int columns, double columnWidth, double columnGap, FlowDocument document, Size pageSize, Thickness pageMargin)
        {
            Document = document;
            Columns = new List<PageColumnElement>();
            PaginationInfo = new PaginationInfo();

            this.Width = pageSize.Width;
            this.MinHeight = pageSize.Height;

            this.HeaderHeight = pageMargin.Top;
            this.HeaderMargin = new Thickness(pageMargin.Left, 0, pageMargin.Right, 0);
            this._ShowHeader = true;

            this.FooterHeight = pageMargin.Bottom;
            this.FooterMargin = new Thickness(pageMargin.Left, 0, pageMargin.Right, 0);
            this._ShowFooter = true;

            this.ContentMargin = new Thickness(pageMargin.Left, 0, pageMargin.Right, 0);

            this.ContentBox = new Rect(new Size(pageSize.Width - pageMargin.Left - pageMargin.Right,
                                                pageSize.Height - pageMargin.Top - pageMargin.Bottom));

            this.ColumnGrid = new Grid();
            for (int i = 0; i < columns; i++)
            {
                var columnDefinition = new ColumnDefinition()
                {
                    Width = new GridLength(columnWidth)
                };
                ColumnGrid.ColumnDefinitions.Add(columnDefinition);

                if (i < columns - 1)
                { 
                    // Add the gap too
                    var gapColumnDefinition = new ColumnDefinition()
                    {
                        Width = new GridLength(columnGap)
                    };
                    ColumnGrid.ColumnDefinitions.Add(gapColumnDefinition);
                }
            }

            this.Template = PageElement.DefaultTemplate;
        }

        #endregion

        #region Properties

        private FlowDocument Document { get; set; }

        public List<PageColumnElement> Columns { get; private set; }

        public SectionElement Section
        {
            get
            {
                if (this.Columns.Count == 0)
                    return null;

                return Columns[0].Section;
            }
        }

        public DataTemplate HeaderTemplate
        {
            get 
            {
                if ((Section == null) || (Section.Source == null))
                    return null;

                return SectionExtensions.GetHeaderTemplate(Section.Source);
            }
        }

        public DataTemplate FooterTemplate
        {
            get
            {
                if ((Section == null) || (Section.Source == null))
                    return null;

                var result = SectionExtensions.GetFooterTemplate(Section.Source);
                return result;
            }
        }

        public double HeaderHeight { get; private set; }

        public double FooterHeight { get; private set; }

        public Thickness HeaderMargin { get; private set; }

        public Thickness FooterMargin { get; private set; }

        public Thickness ContentMargin { get; private set; }

        public Rect ContentBox { get; private set; }

        public bool ShowHeader 
        {
            get
            {
                if (HeaderTemplate == null)
                    return false;

                return _ShowHeader;
            }
            set
            {
                _ShowHeader = value;
            }
        }
        private bool _ShowHeader;

        public bool ShowFooter 
        {
            get
            {
                if (FooterTemplate == null)
                    return false;

                return _ShowFooter;
            }
            set
            {
                _ShowFooter = value;
            }
        }
        private bool _ShowFooter;

        public PaginationInfo PaginationInfo { get; private set; }

        public Grid ColumnGrid { get; private set; }

        #endregion

        #region AddColumn Method

        /// <summary>
        /// Adds a PageColumnElement to this page.
        /// </summary>
        /// <param name="column">The PageColumnElement to be added</param>
        /// <returns>True if this was the last column for the page.</returns>
        public bool AddColumn(PageColumnElement column)
        {
            int position = Columns.Count * 2;

            if (position > 0)
            {
                // Add the rule
                var rule = new Border()
                {
                    Width = Document.ColumnRuleWidth,
                    Background = Document.ColumnRuleBrush,
                    HorizontalAlignment = HorizontalAlignment.Center
                };
                Grid.SetColumn(rule, position -1);
                ColumnGrid.Children.Add(rule);
            }


            Grid.SetColumn(column, position);
            Columns.Add(column);
            ColumnGrid.Children.Add(column);

            return (position >= ColumnGrid.ColumnDefinitions.Count - 1);
        }

        #endregion

        #region Render Methods

        public void Render()
        {
            double height = this.MinHeight;

            Size pageSize = new Size(this.Width, height);
            this.Measure(pageSize);

            pageSize.Height = Math.Max(this.DesiredSize.Height, this.MinHeight);
            Rect pageBounds = new Rect(pageSize);
            this.Arrange(pageBounds);
        }

        #endregion

        #region DefaultTemplate Property

        public static ControlTemplate DefaultTemplate
        {
            get
            {
                if (_DefaultTemplate == null)
                {


                    // Navigate to xaml page
                    Uri uri = new Uri("SmartPaginator;component/Resources/PageElementTemplate.xaml", UriKind.Relative);
                    StreamResourceInfo info = Application.GetResourceStream(uri);
                    XamlReader reader = new XamlReader();
                    _DefaultTemplate = (ControlTemplate)reader.LoadAsync(info.Stream);
                }
                return _DefaultTemplate;
            }
        }
        private static ControlTemplate _DefaultTemplate;

        #endregion
    }
}
